﻿//========================================================= 
/**@file NetworkHelper.h
 * @brief 网络相关辅助接口
 * 
 * @date 2019-10-04   11:42:04
 * @author Zhyioo 
 * @version 1.0
 */ 
//--------------------------------------------------------- 
#ifndef _LIBZHOUYB_NETWORKHELPER_H_
#define _LIBZHOUYB_NETWORKHELPER_H_
//--------------------------------------------------------- 
#include "../../include/Base.h"

#ifdef _MSC_VER
#   include <WinSock2.h>
#else
#   include <sys/stat.h>
#   include <sys/types.h>
#   include <netinet/in.h>
#   include <net/if.h>
#   include <sys/wait.h>
#   include <netinet/in.h>
#   include <arpa/inet.h>
#   include <sys/time.h>
#   include <sys/socket.h>
#   include <sys/ioctl.h>
#endif
//--------------------------------------------------------- 
namespace zhou_yb {
namespace extension {
namespace ability {
//--------------------------------------------------------- 
/**
 * @brief 网络相关辅助接口
 * @date 2019-10-04 11:42
 */
class NetworkHelper
{
protected:
    NetworkHelper() {}
public:
    /**
     * @brief 获取本地IPv4地址
     * @date 2019-10-04 11:43
     */
    static bool GetLocalIPv4(string& ip)
    {
    #ifdef _MSC_VER
        WSADATA WSAData = { 0 };
        if(ERROR_SUCCESS != WSAStartup(MAKEWORD(2, 2), &WSAData))
            return false;

        char hostname[MAX_PATH] = { 0 };
        if(SOCKET_ERROR == gethostname(hostname, MAX_PATH))
            return false;

        struct hostent FAR* lpHostEnt = gethostbyname(hostname);
        if(NULL == lpHostEnt)
            return false;

        LPSTR lpAddr = lpHostEnt->h_addr_list[0];
        struct in_addr inAddr;
        memmove(&inAddr, lpAddr, 4);
        ip = inet_ntoa(inAddr);
        return true;
    #else
        char ip_buff[32] = { 0 };
        struct ifreq intfBuf[32] = { 0 };
        int sockfd = -1;
        struct in_addr stInaddr;
        struct ifconf ifc;
        struct ifreq *ifr;
        struct sockaddr_in sa;
        memset(ip_buff, 0, sizeof(ip_buff));
        sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
        if(sockfd < 0)
            return false;

        memset(&ifc, 0, sizeof(ifc));
        ifc.ifc_len = sizeof(intfBuf);
        ifc.ifc_req = intfBuf;

        if(0 != ioctl(sockfd, SIOCGIFCONF, &ifc))
        {
            close(sockfd);
            return false;
        }

        if(sizeof(intfBuf) <= (unsigned int)ifc.ifc_len)
        {
            close(sockfd);
            return false;
        }

        ifr = ifc.ifc_req;
        ifr = ifc.ifc_req;

        bool is_ok = false;
        for(; (char *)ifr < (char *)ifc.ifc_req + ifc.ifc_len; ++ifr)
        {
            if(ifr->ifr_addr.sa_data == (ifr + 1)->ifr_addr.sa_data)
                continue;

            if(ioctl(sockfd, SIOCGIFFLAGS, ifr))
                continue;

            if((ifr->ifr_flags & IFF_RUNNING) != IFF_RUNNING)
                continue;

            if(strstr(ifr->ifr_name, "eth") != NULL)
            {
                memset(ip_buff, 0, sizeof(ip_buff));
                #define inaddrr(x) (*(struct in_addr *) &ifr->x[sizeof sa.sin_port])
                stInaddr = inaddrr(ifr_addr.sa_data);
                #undef inaddrr
                ip = inet_ntoa(stInaddr);
                is_ok = true;
                break;
            }
        }

        close(sockfd);
        return false;
    #endif
    }
};
//--------------------------------------------------------- 
} // namespace ability 
} // namespace extension 
} // namespace zhou_yb 
//--------------------------------------------------------- 
#endif // _LIBZHOUYB_NETWORKHELPER_H_
//========================================================= 